<?php

/**
 * +----------------------------------------------------------------------
 * | 润憬商城系统 [ 高性价比的通用商城系统 ]
 * +----------------------------------------------------------------------
 * | Copyright (c) 2022~2023 https: *www.honc.fun All rights reserved.
 * +----------------------------------------------------------------------
 * | Licensed 这不是一个自由软件，不允许对程序代码以任何形式任何目的的再发行
 * +----------------------------------------------------------------------
 * | Author: 润憬科技 Hon(陈烁临) <2275604210@qq.com>
 * +----------------------------------------------------------------------
 */

namespace app\api\service\passport;

use support\Cache;
use Webman\Captcha\CaptchaBuilder;
use Webman\Captcha\PhraseBuilder;

class CaptchaApi
{
  // 验证码字符集合
  protected $codeSet = '2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY';
  // 验证码过期时间（s）
  protected $expire = 1800;
  // 验证码位数
  protected $length = 4;
  //算术验证码
  protected $math = false;
  //验证码可重复验证的次数
  protected $checkTimes = 5;

  public  function create()
  {
    $builder = new PhraseBuilder($this->length, $this->codeSet);
    $captcha = new CaptchaBuilder(null, $builder);
    $captcha->build();
    $key = mb_strtolower($captcha->getPhrase(), 'UTF-8');
    $hash = password_hash($key, PASSWORD_DEFAULT, ['cost' => 10]);
    $hashKey = md5($hash);
    Cache::set("captchaApi.{$hashKey}", ['code' => $key, 'times' => $this->checkTimes], $this->expire);
    $content = $captcha->get();
    return [
      'base64' => 'data:image/png;base64,' . chunk_split(base64_encode($content)),
      'key' => $hash,
      'code' => $key,
      'md5' => md5($key),
    ];
  }
  /**
   * 生成短信验证码并把验证码的值保存的缓存中
   * @access public
   * @param string $phone
   * @return object
   */
  public  function createSMS(string $phone): array
  {
    $code = (string)mt_rand(100000, 999999);
    Cache::set("captchaSMS.{$phone}", ['code' => $code, 'times' => $this->checkTimes], $this->expire);
    return ['key' => $phone, 'code' => $code];
  }

  /**
   * 验证短信验证码是否正确
   * @access public
   * @param string $code
   * @param string $phone
   * @return object
   */
  public function checkSMS(string $code, string $phone): bool
  {
    $captcha = Cache::get("captchaSMS.{$phone}");
    if (empty($captcha)) {
      throwError('短信验证码不存在，请重新获取');
    }
    if ($captcha['times'] <= 0) {
      Cache::delete("captchaSMS.{$phone}");
      throwError('短信验证码已超出错误次数，请重新获取');
    }
    if ($captcha['code'] != $code) {
      Cache::set("captchaSMS.{$phone}", ['times' => $captcha['times'] - 1]);
      throwError('短信验证码不正确，请重新填写');
    }
    Cache::delete("captchaSMS.{$phone}");
    return true;
  }

  /**
   * 验证图形验证码是否正确
   * @access public
   * @param string $code 用户验证码
   * @param string $key 用户验证码key
   * @return bool 用户验证码是否正确
   * @throws Exception
   */
  public function check(string $code, string $key): bool
  {
    $hashKey = md5($key);
    $captcha = Cache::get("captchaApi.{$hashKey}");
    if (empty($captcha)) {
      throwError('图形验证码不存在，请重新获取');
    }
    if ($captcha['times'] <= 0) {
      Cache::delete("captchaApi.{$key}");
      throwError('图形验证码已超出错误次数，请重新获取');
    }
    if (password_verify(mb_strtolower($code, 'UTF-8'), $key) === false) {
      $captcha['times'] = $captcha['times'] - 1;
      Cache::set("captchaApi.{$hashKey}", $captcha);
      return false;
    }
    Cache::delete("captchaApi.{$hashKey}");
    return true;
  }
}
